<?php
/**
 +------------------------------------------------------------------------------
 * model for framework
 * model是底层数据库驱动的兼容层，直接调用数据库驱动
 +------------------------------------------------------------------------------
 * @version   1.4
 * @author    WangXian
 * @package ephp
 * @filename model.class.php
 * @creation date 2010-8-23
 * @modified date 2010-8-26 14:46:12
 +------------------------------------------------------------------------------
 */

class model
{
	private $table_name = '';
	private $field = '';
	private $orderby = '';
	private $groupby = '';
	private $limit = '';
	private $where = '';
	private $set_string = '';
	
	
	private $db_change = false; // 是否进行db切换
	
	private $db='';
	/**
	 * 连接数据库
	 * @param String $db_config
	 * @return Resource $db Connection
	 * @return Object $this
	 */
	protected function conn()
	{
		if(empty($this->db_config_name)) $this->db_config_name = 'default';
		
		// 这里判断是不是真的要连接数据库， 连接数据库有2种情况：
		// 1.之前没有数据库连接; 2.需要连接别的MySQL SERVER
		if(! is_object($this->db) || ($this->db_change == true))
		{
			$this->db = new db($this->db_config_name);
		}
		
		return $this;
	}
	
	/**
	 +----------------------------------------------------------
	 * 调用数据库db::query方法
	 +----------------------------------------------------------
	 * @param string sql SQL语句
	 * @param string var2 var_description2
	 +----------------------------------------------------------
	 * @return boolean
	 +----------------------------------------------------------
	 */
	public function query($sql)
	{
		//到最后一步才去连接数据库，减小类开销
		$this->conn();
		if($this->db->query($sql))
			return true;
		else
		{
			throw new ephpException($this->db->get_error(), 6002);
			return false;
		}
	}
	/**
	 +----------------------------------------------------------
	 * 以array的方式，返回多条查询结果
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return array
	 +----------------------------------------------------------
	 */
	public function findAll()
	{
		//到最后一步才去连接数据库，减小类开销
		$this->conn();
		
		return $this->db->fetch_arrays($this->_read_sql());
	}
	
	/**
	 +----------------------------------------------------------
	 * findAll()的别名，查询多行数据
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return array
	 +----------------------------------------------------------
	 */
	public function fetchAll()
	{
		return $this->findAll();
	}
	
	/**
	 +----------------------------------------------------------
	 * find()的别名，获取一行
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return array
	 +----------------------------------------------------------
	 */
	public function fetch()
	{
		return $this->find();
	}
	
	/**
	 +----------------------------------------------------------
	 * 以object的方式返回查询结果
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return object
	 +----------------------------------------------------------
	 */
	public function findObj()
	{
		//到最后一步才去连接数据库，减小类开销
		$this->conn();
		
		return $this->db->fetch_object($this->_read_sql());
	}

	/**
	 +----------------------------------------------------------
	 * 以objects的方式返回所有的查询结果
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return object
	 +----------------------------------------------------------
	 */
	public function fetchObjs()
	{
		//到最后一步才去连接数据库，减小类开销
		$this->conn();
		
		return $this->db->fetch_objects($this->_read_sql());
	}
	/**
	 +----------------------------------------------------------
	 * 以array的方式返回查询结果
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return array
	 +----------------------------------------------------------
	 */
	public function find()
	{
		//到最后一步才去连接数据库，减小类开销
		$this->conn();
		
		return $this->db->fetch_array($this->_read_sql());
	}
	/**
	 +----------------------------------------------------------
	 * 组装read方式的sql语句
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return string sql语句
	 +----------------------------------------------------------
	 */
	private function _read_sql()
	{
		$_field = empty($this->field)?'*':$this->field;
		$_table_name = $this->_get_table_name();
		
		$_where = empty($this->where)?'':' WHERE '.$this->where;
		$_orderby = empty($this->orderby)?'':' ORDER BY '.$this->orderby;
		$_groupby = empty($this->groupby)?'':' GROUP BY '.$this->groupby;
		$_limit = empty($this->limit)?'':' LIMIT '.$this->limit;
		
		$sql = 'SELECT '.$_field.' FROM '.$_table_name.$_where.$_orderby.$_groupby.$_limit;
		$this->db->sql = $sql;
		
		//清理使用过的变量
		$this->_clear_var();
		return $sql;
	}
	/**
	 +----------------------------------------------------------
	 * 获取table_name
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return string $_table_name
	 +----------------------------------------------------------
	 */
	protected function _get_table_name()
	{
		if(! empty($this->table_name))
		{
			$_table_name = $this->table_name;
		}
		else
		{
			//如果是在实例化后使用，则使用当前模型名称
			$current_class = get_class($this);
			if($current_class == 'model')
				throw new ephpException('table_name无法确定！', 6002);
			else
				$_table_name = substr($current_class,0,strlen($current_class) - 5);
		}
		
		return $_table_name;
	}
	/**
	 +----------------------------------------------------------
	 * model进行update更新数据库，如果希望更新所有的数据，
	 * 即不加where条件，则将$f置为true，默认false
	 +----------------------------------------------------------
	 * @param string $f false 默认，true 执行update不带where子句
	 +----------------------------------------------------------
	 * @return boolean
	 +----------------------------------------------------------
	 */
	public function update($f=false)
	{
		$_where = '';
		$_table_name = $this->_get_table_name();
		$_set_string = empty($this->set_string)?'':' SET '.$this->set_string;
		if(empty($this->where) && ($f == false))
			throw new ephpException('警告：执行update操作需要有where子条件，如果你需要无where子句操作，请把使用M()::update(true)', 6003);
		elseif(! empty($this->where))
		{
			$_where = ' WHERE '.$this->where;
		}

		$this->conn();
		$this->db->sql='UPDATE '.$_table_name.$_set_string.$_where;

		//清理使用过的变量
		$this->_clear_var();
		return $this->db->query($this->db->sql);
	}
	/**
	 +----------------------------------------------------------
	 * model进行delete删除数据库，如果希望删除所有数据
	 * 即不加where条件，则将$f置为true，默认false
	 +----------------------------------------------------------
	 * @param string $f false 默认，true 执行update不带where子句
	 +----------------------------------------------------------
	 * @return boolean
	 +----------------------------------------------------------
	 */
	public function delete($f=false)
	{
		$_where = '';
		$_table_name = $this->_get_table_name();
		if(empty($this->where) && ($f == false))
			throw new ephpException('警告：执行delete操作需要有where子条件，如果你需要无where子句操作，请把使用M()::delete(true)', 6004);
		elseif(! empty($this->where))
		{
			$_where = ' WHERE '.$this->where;
		}
		$this->conn();
		$this->db->sql='DELETE FROM '.$_table_name.$_where;
		
		//清理使用过的变量
		$this->_clear_var();
		return $this->db->query($this->db->sql);
	}
	
	/**
	 +----------------------------------------------------------
	 * model 写入数据库操作，返回插入id
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return integer 最后插入的id
	 +----------------------------------------------------------
	 */
	public function insert()
	{
		$_table_name = $this->_get_table_name();
		$_set_string = empty($this->set_string)?'':' SET '.$this->set_string;
		
		$this->conn();
		$this->db->sql='INSERT INTO '.$_table_name.$_set_string;
		
		//清理使用过的变量
		$this->_clear_var();
		return $this->db->query($this->db->sql);
	}
	
	/**
	 +----------------------------------------------------------
	 * insert()的别名
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return void
	 +----------------------------------------------------------
	 */
	public function add()
	{
		return $this->insert();
	}
	
	/**
	 +----------------------------------------------------------
	 * 清理使用过的变量
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return void
	 +----------------------------------------------------------
	 */
	private function _clear_var()
	{
		$this->table_name = NULL;
		$this->field = NULL;
		$this->orderby = NULL;
		$this->groupby = NULL;
		$this->limit = NULL;
		$this->where = NULL;
		$this->set_string = NULL;
		$this->db_change = NULL;
		
		return '';
	}
	/**
	 +----------------------------------------------------------
	 * 返回影响的数据行数
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return integer
	 +----------------------------------------------------------
	 */
	public function affected_rows()
	{
		return $this->db->affected_rows();
	}
	
	/**
	 +----------------------------------------------------------
	 * 返回刚插入的insert_id
	 +----------------------------------------------------------
	 +----------------------------------------------------------
	 * @return integer
	 +----------------------------------------------------------
	 */
	public function insert_id()
	{
		return $this->db->insert_id();
	}
	/**
	 * 查询的表名
	 * @param String $table_name
	 * @return Object $this
	 */
	public function table($table_name)
	{//trim(get_class($this), 'Model')
		$this->table_name = $table_name;
		return $this;
	}
	
	/**
	 * table()方法的别名
	 * @param String $table_name
	 */
	public function from($table_name)
	{
		$this->table($table_name);
		return $this;
	}
	public function dbconfig($db_config_name)
	{
		// 是否需要重新连接数据了
		if(! empty($this->db_config_name) && ($this->db_config_name != $db_config_name) )
		{
			$this->db_change = true;
		}
		$this->db_config_name = $db_config_name;
		
		return $this;
	}

	/**
	 * 查询出结果的字段，也就是sql中字段列表
	 * @param String $field
	 * @return Object $this
	 */
	public function field($field)
	{
		$this->field = $field;
		return $this;
	}
	/**
	 * SQL limit
	 * @param String $limit
	 * @return Object $this
	 */
	public function limit($limit)
	{
		$this->limit = $limit;
		return $this;
	}
	
	/**
	 +----------------------------------------------------------
	 * field()的别名
	 +----------------------------------------------------------
	 * @param string $field select的字段列表
	 +----------------------------------------------------------
	 * @return object $this
	 +----------------------------------------------------------
	 */
	public function select($field)
	{
		$this->field($field);
		return $this;
	}
	/**
	 * where条件
	 * @param String $field
	 * @return Object $this
	 */
	public function where($where)
	{
		$this->where = $where;
		return $this;
	}
	/**
	 * order by排序
	 * @param String $orderby
	 * @return Object $this
	 */
	public function orderby($orderby)
	{
		$this->orderby = $orderby;
		return $this;
	}
	/**
	 +----------------------------------------------------------
	 * SQL group by
	 +----------------------------------------------------------
	 * @param string $groupby 分组
	 +----------------------------------------------------------
	 * @return object $this
	 +----------------------------------------------------------
	 */
	public function groupby($groupby)
	{
		$this->groupby = $groupby;
		return $this;
	}
	
	/**
	 * 把需要处理的data进行格式化处理，以便在insert和update中使用.
	 * 1。支持直接写string语句
	 * 2。支持设置不加引号字段，sql中用函数
	 * @param $data 写入数据库的string
	 * @param $noquote 不用加引号的字段，也是就要使用mysql函数
	 * @return object
	 */
	public function data($data,$noquote='')
	{
		//如果是string，则直接返回
		if(is_string($data))
		{
			$this->set_string = $data;
			return $this;
		}
		
		//拼接sql语句，可以在insert和update中使用
		if(is_array($data))
		{
			foreach ($data as $k=>$v)
			{
				// 当noquote是字符串并和noquote相等是不加引号，或者，noquote是数组并且key在noquote中时，不加引号。
				if( (is_string($noquote) && $k != $noquote) || (is_array($noquote) && !in_array($k,$noquote)) )
					$tmp[] = $k."='".$v."'";
				else
					$tmp[] = $k."=".$v;
				
			}
			$this->set_string = implode(',', $tmp);
		}
		return $this;
	}
	/**
	 * 最后执行的sql语句
	 */
	public function getLastSql()
	{
		return $this->db->sql;
	}
}


/* End of file model.class.php */
/* Location: model.class.php */